package com.ivan.toolkit.common;

import java.util.HashMap;
import java.util.Optional;
import java.util.Set;

public interface Any {

    public <T> Optional<T> get(Object key, Class<T> cls);
    
    default
    public <T> Optional<T> get(Class<T> cls) {
    	return get(cls, cls);
    }
	
    public Any set(Object key, Object value);
    
    default
	public Any set(Object value) {
    	set(value.getClass(), value);
    	return this;
    }
    
    public Any set(Any another);
    
    public Set<Object> keys();
    
    public static Any of() {
    	return new MappedAny();
    }
    
    static class MappedAny extends HashMap<Object, Object> implements Any {
    	
		private static final long serialVersionUID = 6641006343816018732L;

		public MappedAny() {
    		super();
    	}

		@Override
		public <T> Optional<T> get(Object key, Class<T> cls) {
        	try {
        		return Optional.ofNullable(cls.cast(this.get(key)));
        	} catch (Exception e ){
        		return Optional.empty();
        	}
		}

		@Override
		public Any set(Object key, Object value) {
			this.put(key, value);
			return this;
		}

		@Override
		public Any set(Any another) {
        	if(another != null) {
        		another.keys().forEach(k-> {
        			another.get(k, Object.class).ifPresent(v->this.set(k, v));
        		});
        	}
        	return this;
		}

		@Override
		public Set<Object> keys() {
			return this.keySet();
		}

    }
    
}
